/*
 * @Descripttion:
 * @version:
 * @Author: lfzxs@qq.com
 * @Date: 2022-10-12 14:11:41
 * @LastEditors: lfzxs@qq.com
 * @LastEditTime: 2022-12-06 16:03:27
 */
package file

import (
	"io"
	"log"
	"strings"

	"gitee.com/g_boot/gfextend/common/system"
	hctypes "gitee.com/g_boot/gfextend/types"
	"github.com/gogf/gf/errors/gcode"
	"github.com/gogf/gf/errors/gerror"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/gctx"
	btypes "go.beyondstorage.io/v5/types"
)

const (
	// 默认配置为同目录下的files目录
	DefaultInstanceName = "default"
)

var (
	FileSysMrg = fileSysMrg{}
)

type fileSysMrg struct {
	// 默认
	defFileSys  ILogicFile
	fileSysList map[string]ILogicFile
}

// 逻辑文件操作
type ILogicFile interface {
	// 写入文件
	WriteFile(path string, r io.Reader, size int64, pairs ...hctypes.Pair) (writeSize int64, err error)

	// 追加文件
	AppendFile(path string, r io.Reader, size int64, pairs ...hctypes.Pair) (writeSize int64, err error)

	// 读取文件
	ReadFile(path string) (data []byte, err error)

	// 随机读取
	ReadRange(path string, start int64, size int64) (data []byte, err error)

	// 删除文件
	RemoveFile(path string) (err error)

	// 重命名文件
	RenameFile(path string, name string) (err error)

	// 文件列表
	ListFile(path string) (oi *btypes.ObjectIterator, err error)

	// 判断文件是否存在
	Exists(path string) (yes bool)

	// 获取文件信息
	FileInfo(path string) (pairs []hctypes.Pair, err error)

	// 复制文件
	CopyFile(source string, dest string) (err error)

	// 移动文件
	MoveFile(source string, targetDir string) (err error)

	// 创建目录
	CreateDir(path string, dirName string) (dirpath string, err error)

	// 移动目录
	MoveDir(source string, dest string) (err error)

	// 删除目录
	RemoveDir(path string) (err error)

	// 目录信息
	DirInfo(path string) (pairs []hctypes.Pair, err error)
	// 重命名文件
	RenameDir(path string, name string) (err error)

	// 获取连接串
	GetConnstr() string
}

func (mrg *fileSysMrg) Regist(name string, fileMrg ILogicFile) error {
	_, ok := mrg.Get(name)
	if ok {
		err := gerror.NewCode(gcode.CodeOperationFailed, "系统已存在!")

		return err
	}

	mrg.fileSysList[name] = fileMrg

	if mrg.defFileSys == nil {
		mrg.defFileSys = fileMrg
	}

	return nil
}

// 注销
func (mrg *fileSysMrg) UnRegist(name string) error {
	delete(mrg.fileSysList, name)

	return nil
}

// 获取管理器
func (mrg *fileSysMrg) Get(name string) (ILogicFile, bool) {
	if nil == mrg.fileSysList {
		mrg.fileSysList = make(map[string]ILogicFile)
	}
	val, ok := mrg.fileSysList[name]
	return val, ok
}

func (mrg *fileSysMrg) GetOrCreate(name string) (ILogicFile, bool) {

	val, ok := mrg.Get(name)
	if !ok { //不存在就创建
		connstr := mrg.getConnStr(name)
		if len(connstr) > 0 {
			val = mrg.createStorager(connstr)
			if nil != val {
				mrg.Regist(name, val)
				return val, true
			}
		}

		if len(connstr) <= 0 && strings.EqualFold(name, DefaultInstanceName) {
			val = DefaultLogicFile()
			if nil != val {
				mrg.Regist(name, val)
				return val, true
			}
		}
	}

	return val, ok
}

func (mrg *fileSysMrg) getConnStr(name string) string {
	var (
		ctx = gctx.New()
	)

	connStr, _ := g.Cfg().Get(ctx, "fileStorage."+name+".connStr")
	// connStr := g.Cfg().GetString("fileStorage." + name + ".connStr")
	return connStr.String()
}

func (mrg *fileSysMrg) createStorager(connStr string) ILogicFile {
	fileMrg, err := CreateStorager(connStr)

	if err != nil {
		//使用系统日志类
		log.Printf("默认ILogicFile创建失败:" + connStr)
		return nil
	}
	return fileMrg
}

func DefaultLogicFile() ILogicFile {

	// var(
	// 	defConnStr string
	// )

	// if len(connStr) == 0 {

	// }

	defConnStr := "fs://" + system.RootPath() + "files"

	fileMrg, err := CreateStorager(defConnStr)

	if err != nil {
		//使用系统日志类
		log.Printf("默认ILogicFile创建失败:" + defConnStr)
		return nil
	}
	return fileMrg
}

func Instance(name ...string) ILogicFile {
	var instanceName = DefaultInstanceName
	if len(name) > 0 && name[0] != "" {
		instanceName = name[0]
	}

	fiSys, has := FileSysMrg.GetOrCreate(instanceName)

	if !has {
		log.Printf("标识为[%s]的文件系统不存在或配置错误\n", instanceName)
	}

	//connStr := g.Cfg().Get("fileStorage." + instanceName + ".connStr")

	return fiSys
}
